﻿#include "GUISEASubSysCavityDialog.h"
#include "ui_GUISEASubSysCavityDialog.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"

#include "FITK_Kernel/FITKCore/FITKActionOperator.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysCavity.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysAbsShell.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysGeoProp.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsMaterial.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsSpectraManager.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbstractSpectra.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsNCT.h"
#include "PickDataProvider/PickedDataProvider.h"
#include "PickDataProvider/PickedData.h"

#include <QStandardItemModel>
#include <QMessageBox>
#include <QHeaderView>

namespace GUI 
{
    GUISEASubSysCavityDialog::GUISEASubSysCavityDialog(Acoustics::FITKSEASubSysCavity* obj, Core::FITKActionOperator* oper, QWidget* parent /*= nullptr*/) :
        GUISEASubSysBaseDialog(obj, oper, parent),
        _ui(new Ui::GUISEASubSysCavityDialog)
    {
       _ui->setupUi(this);
       _ui->tableView->installEventFilter(this);

       _model = new QStandardItemModel();

       if (!_obj->getGeoProp())return;
    //设置 体积 面积 周长 模态密度 的重载信号
       connect(_ui->checkBox_volume, &QCheckBox::stateChanged, this, [this](int state){    
           if (state == Qt::Checked) { _ui->lineEdit_volume->setEnabled(true); }
           else if (state == Qt::Unchecked) {
               _ui->lineEdit_volume->setEnabled(false);
               _ui->lineEdit_volume->setText(QString("%1").arg(_obj->getGeoProp()->getGeoProp(Acoustics::FITKSEASubSysGeoProp::GeoPropType::Volume)));
           }});
       connect(_ui->checkBox_Surface, &QCheckBox::stateChanged, this, [this](int state){
           if (state == Qt::Checked) { _ui->lineEdit_Surface->setEnabled(true); }
           else if (state == Qt::Unchecked) {
               _ui->lineEdit_Surface->setEnabled(false);
               _ui->lineEdit_Surface->setText(QString("%1").arg(_obj->getGeoProp()->getGeoProp(Acoustics::FITKSEASubSysGeoProp::GeoPropType::Area)));
           }});
       connect(_ui->checkBox_Perimeter, &QCheckBox::stateChanged, this, [this](int state){
           if (state == Qt::Checked) { _ui->lineEdit_Perimeter->setEnabled(true); }
           else if (state == Qt::Unchecked) { 
               _ui->lineEdit_Perimeter->setEnabled(false); 
               _ui->lineEdit_Perimeter->setText(QString("%1").arg(_obj->getGeoProp()->getGeoProp(Acoustics::FITKSEASubSysGeoProp::GeoPropType::Circumference)));
           }});
       connect(_ui->checkBox_ModalDensity, &QCheckBox::stateChanged, this, [this](int state) {
           if (state == Qt::Checked) { _ui->comboBox_ModalDensity->setEnabled(true); }
           else if (state == Qt::Unchecked) { _ui->comboBox_ModalDensity->setEnabled(false); }});
    //初始化
       _ui->label_4->setPixmap(QPixmap(":/icons/cavity1.png"));
       _ui->label_11->setPixmap(QPixmap(":/icons/cavity2.png"));
       initComponent();
       initData();
    }

    GUISEASubSysCavityDialog::~GUISEASubSysCavityDialog()
    {
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
    }

    void GUISEASubSysCavityDialog::initComponent()
    {
    //General板块ui初始化
        QString name = _obj->getDataObjectName();
        if (name.isEmpty())
            name = this->ckeckNameFromMgr("Cavity");
        _ui->lineEdit_Name->setText(name);
        _ui->radioButton_Damping->setChecked(true);
        //初始化物理属性下拉列表
        Acoustics::FITKAcousticsMaterialManager* materialMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>()->getMaterialManager();
        if (!materialMgr)return;
        QList<Acoustics::FITKAcousticsAbsMaterial*> materials = materialMgr->getAcousticsMaterials(Acoustics::FITKAcousticsAbsMaterial::Fluid);
        if (!materials.isEmpty()) {
            for (auto material : materials) {
                if (!material)continue;
                _ui->comboBox_Fluid->addItem(material->getDataObjectName(), material->getDataObjectID());
            }
        }
        //初始化损耗因子下拉列表
        Acoustics::FITKAcousticsSpectraManager* spectraMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>()->getFITKAcousticsSpectraManager();
        if (!spectraMgr)return;
        QList<Acoustics::FITKAcousticsAbstractSpectra*> spectraList = spectraMgr->getSpectraByType(Acoustics::FITKAcousticsAbstractSpectra::Damping);
        if (!spectraList.isEmpty()) {
            for (auto spectra : spectraList) {
                if (!spectra)continue;
                _ui->comboBox_Damping->addItem(spectra->getDataObjectName(), spectra->getDataObjectID());
            }
        }
        //初始化吸收系数频谱下拉列表
        QList<Acoustics::FITKAcousticsAbstractSpectra*> absorptionList = spectraMgr->getSpectraByType( Acoustics::FITKAcousticsAbstractSpectra::Absorption);
        if (!absorptionList.isEmpty()) {
            for (auto absorption : absorptionList) {
                if (!absorption)continue;
                _ui->comboBox_Average->addItem(absorption->getDataObjectName(), absorption->getDataObjectID());
            }
        }
    //Faces板块ui初始化    
        _ui->tableView->setModel(_model);
        _ui->tableView->resizeColumnsToContents();
        _model->setColumnCount(4);
        _model->setHeaderData(0, Qt::Horizontal, "Face Name");
        _model->setHeaderData(1, Qt::Horizontal, " Noise Control Treatment ");
        _model->setHeaderData(2, Qt::Horizontal, "Area [m2]");
        _model->setHeaderData(3, Qt::Horizontal, "Coverage(%)");
        _ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        _ui->tableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents);

    //Geometry板块ui初始化
        //只能输入数字
        _ui->lineEdit_volume->setValidator(new QRegExpValidator(QRegExp("^-?(\\d+(\\.\\d+)?)$")));
        _ui->lineEdit_Surface->setValidator(new QRegExpValidator(QRegExp("^-?(\\d+(\\.\\d+)?)$")));
        _ui->lineEdit_Perimeter->setValidator(new QRegExpValidator(QRegExp("^-?(\\d+(\\.\\d+)?)$")));

    //Pressure板块ui初始化  
        //压力选项默认选中
        _ui->checkBox_SMS->setChecked(true);
        _ui->comboBox_Average->setEnabled(false);
        //初始化模态密度下拉列表
        QList<Acoustics::FITKAcousticsAbstractSpectra*> densityList = spectraMgr->getSpectraByType(Acoustics::FITKAcousticsAbstractSpectra::ModalDensity);
        if (!densityList.isEmpty()) {
            for (auto density : densityList) {
                if (!density)continue;
                _ui->comboBox_ModalDensity->addItem(density->getDataObjectName(), density->getDataObjectID());
            }
        }
        _ui->comboBox_ModalDensity->setEnabled(false);
    }

    void GUISEASubSysCavityDialog::initData()
    {
        Acoustics::FITKSEASubSysCavity* cavityData = dynamic_cast<Acoustics::FITKSEASubSysCavity*>(_obj);
        if (!cavityData) return;
    //Faces板块数据初始化    
        int ShellCount = cavityData->getShellCount();
        if (ShellCount == 0)return;
        //获取声学包管理器
        Acoustics::FITKAcousticsNCTManager* nctMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>()->getFITKAcousticsNCTManager();
        if (!nctMgr)return;
        Acoustics::FITKSEASubSysGeoProp* geoProp = cavityData->getGeoProp();
        if (!geoProp)return;
        //总面积
        double areas = 0;
        //声腔的板周长和
        double perimeter = 0;
        //初始化每块板的信息
        QList<int>shellIDs;
        for (int i = 0; i < ShellCount;++i) {
            Acoustics::FITKAbstractSEASubSysShell* shell = cavityData->getShell(i);
            if (!shell)continue;
            shellIDs.push_back(shell->getDataObjectID());
            int shellDirOnCavity = geoProp->getShellDirOnCavity(shell->getDataObjectID());
            if (shellDirOnCavity == 0)return;
        //板的覆盖率
            double covered = 0;
            if (shellDirOnCavity > 0) {
                covered = shell->getOutsideNCTCoveredArea();
            }else {
                covered = shell->getInsideNCTCoveredArea();
            }
        //板的面积
            double area = geoProp->getGeoProp(Acoustics::FITKSEASubSysGeoProp::GeoPropType::Area);
            areas += area;
        //声腔的周长
            //perimeter+= geoProp->getGeoProp(Acoustics::FITKSEASubSysGeoProp::GeoPropType::Circumference);
        //板的名称
            QString name=shell->getDataObjectName();    
        //添加声学包
            QComboBox* cmb = new QComboBox();
            cmb->addItem("None", -1);
            for (int i = 0; i < nctMgr->getDataCount(); ++i)
            {
                Acoustics::FITKAcousticsAbsNCT* nctData = nctMgr->getDataByIndex(i);
                if (!nctData)continue;
                cmb->addItem(nctData->getDataObjectName(), nctData->getDataObjectID());
            }
        //填入表格
            _model->setItem(i, 0, new QStandardItem(name));
            _model->item(i, 0)->setFlags(Qt::NoItemFlags);
            _ui->tableView->setIndexWidget(_model->index(i, 1), cmb);
            _model->setItem(i, 2, new QStandardItem(QString("%1").arg(area)));
            _model->item(i, 2)->setFlags(Qt::NoItemFlags);
            _model->setItem(i, 3, new QStandardItem(QString("%1").arg(covered)));
        }      
        QVariant listdata= QVariant::fromValue(shellIDs);
        _oper->setArgs("shellIDs", listdata);//存储每块板的id

    //Geometry板块数据初始化
        QString numF = QString("%1").arg(cavityData->getShellCount());
        //板的个数
        _ui->lineEdit_NumFaces->setText(numF);
        _ui->lineEdit_NumFaces->setReadOnly(true);
        //声腔的总面积
        _ui->lineEdit_Surface->setText(QString("%1").arg(areas));
        _ui->lineEdit_Surface->setEnabled(false);
        //声腔的体积
        if (!_obj->getGeoProp())return;
        double volume=_obj->getGeoProp()->getGeoProp(Acoustics::FITKSEASubSysGeoProp::GeoPropType::Volume);
        _ui->lineEdit_volume->setText(QString("%1").arg(volume));
        _ui->lineEdit_volume->setEnabled(false);
        //声腔的板周长和
        perimeter= _obj->getGeoProp()->getGeoProp(Acoustics::FITKSEASubSysGeoProp::GeoPropType::Circumference);
        _ui->lineEdit_Perimeter->setText(QString("%1").arg(perimeter));
        _ui->lineEdit_Perimeter->setEnabled(false);

        if (!_isCreate)
        {
            initUserData();
        }
    }

    void GUISEASubSysCavityDialog::initUserData()
    {
        Acoustics::FITKSEASubSysCavity* cavityData = dynamic_cast<Acoustics::FITKSEASubSysCavity*>(_obj);
        if (!cavityData) return;
    //General板块用户设置数据初始化
        int fluidID = cavityData->getMaterialID();
        int index = _ui->comboBox_Fluid->findData(fluidID);
        _ui->comboBox_Fluid->setCurrentIndex(index );
        int dampingID = cavityData->getDampingID();
        if (dampingID != 0) {
            int type = cavityData->getDampingType();
            switch (type) {
            case Acoustics::FITKAcousticsAbstractSpectra::None: {
                _ui->radioButton_Absorption->setChecked(true);
                break;
            }
            case Acoustics::FITKAcousticsAbstractSpectra::Damping: {
                _ui->radioButton_Damping->setChecked(true);
                int index = _ui->comboBox_Damping->findData(dampingID);
                _ui->comboBox_Damping->setCurrentIndex(index);
                break;
            }
            case Acoustics::FITKAcousticsAbstractSpectra::Absorption: {
                _ui->radioButton_Average->setChecked(true);
                int index = _ui->comboBox_Average->findData(dampingID);
                _ui->comboBox_Average->setCurrentIndex(index);
                break;
            }
            default:
                break;
            }
        }
    //Faces板块用户设置数据初始化
        if (!_obj->getGeoProp())return;
        for (int i = 0; i < cavityData->getShellCount(); ++i) {
            Acoustics::FITKAbstractSEASubSysShell* shell = cavityData->getShell(i);
            if (!shell)continue;
            int shellDirOnCavity = _obj->getGeoProp()->getShellDirOnCavity(shell->getDataObjectID());
            if (shellDirOnCavity == 0)return;
            //读取板的声学包和覆盖率
            QComboBox* cmb = dynamic_cast<QComboBox*>(_ui->tableView->indexWidget(_model->index(i, 1)));
            if (!cmb)return;
            if (shellDirOnCavity > 0) {
                int NCTid = shell->getOutsideNCTID();
                int index = cmb->findData(NCTid);
                cmb->setCurrentIndex(index);
                double covered = shell->getOutsideNCTCoveredArea();
                _model->setItem(i, 3, new QStandardItem(QString("%1").arg(covered)));
            }
            else {
                int NCTid = shell->getInsideNCTID();
                int index = cmb->findData(NCTid);
                cmb->setCurrentIndex(index);
                double covered = shell->getInsideNCTCoveredArea();
                _model->setItem(i, 3, new QStandardItem(QString("%1").arg(covered)));
            }
        }
    //Geometry板块用户设置数据初始化
        if (cavityData->isOverride(1)) {
            _ui->checkBox_volume->setChecked(true);
            _ui->lineEdit_volume->setText(QString("%1").arg(cavityData->getVolume()));
        }
        if (cavityData->isOverride(2)) {
            _ui->checkBox_Surface->setChecked(true);
            _ui->lineEdit_Surface->setText(QString("%1").arg(cavityData->getSurfaceArea()));
        }
        if (cavityData->isOverride(3)) {
            _ui->checkBox_Perimeter->setChecked(true);
            _ui->lineEdit_Perimeter->setText(QString("%1").arg(cavityData->getPerimeter()));
        }
    //Pressure板块用户设置数据初始化
        _ui->checkBox_SMS->setChecked(cavityData->getInSEAMatrixSolution());
        int MDid = cavityData->getModalDensity();
        if (MDid != -1) {
            _ui->checkBox_ModalDensity->setChecked(true);
            int index = _ui->comboBox_ModalDensity->findData(MDid);
            _ui->comboBox_ModalDensity->setCurrentIndex(index);
        }
    }

    void GUISEASubSysCavityDialog::getDataFormWidget()
    {
        Acoustics::FITKSEASubSysCavity* cavityData = dynamic_cast<Acoustics::FITKSEASubSysCavity*>(_obj);
        if (!cavityData) return;
    //General板块数据提取
        //设置填充声腔的流体材料ID
        _obj->setMaterialID(_ui->comboBox_Fluid->currentData().toInt());
        _pyStr.append(QString("seaSubSys.setFiuld('%1')").arg(_ui->comboBox_Fluid->currentText()));
        //设置阻尼ID
        int ID;
        if (_ui->radioButton_Damping->isChecked()) 
        {
            ID = _ui->comboBox_Damping->currentData().toInt();
            _pyStr.append(QString("seaSubSys.setDamping('%1')").arg(_ui->comboBox_Damping->currentText()));
        }
        else if (_ui->radioButton_Absorption->isChecked()) 
        {
            ID = -1;
            _pyStr.append(QString("seaSubSys.setDamping('')"));
        }
        else if(_ui->radioButton_Average->isChecked())
        {
            ID = _ui->comboBox_Average->currentData().toInt();
            _pyStr.append(QString("seaSubSys.setDamping('%1')").arg(_ui->comboBox_Average->currentText()));
        }
        cavityData->setDampingID(ID);

    //Faces板块数据提取
        bool ok = false;
        for (int i = 0; i < cavityData->getShellCount(); ++i) {
            Acoustics::FITKAbstractSEASubSysShell* shell = cavityData->getShell(i);
            if (!shell)continue;
            _pyStr.append(QString("shell=SEA.SEAShell.GetSEAShell('%1')").arg(shell->getDataObjectName()));
            int shellDirOnCavity = cavityData->getGeoProp()->getShellDirOnCavity(shell->getDataObjectID());
            if (shellDirOnCavity == 0)return;
            //存入板的声学包和覆盖率
            QComboBox* cmb = dynamic_cast<QComboBox*>(_ui->tableView->indexWidget(_model->index(i, 1)));
            if (!cmb || !_model->item(i, 3))continue;
            double covered = _model->item(i, 3)->text().toDouble(&ok);
            if (!ok) {
                QMessageBox::warning(this, "", tr("The coverage must be 0% to 100%"), QMessageBox::Ok);
                return;
            }
            if (shellDirOnCavity > 0) 
            {
                _pyStr.append(QString("shell.setNCT(1,%1,'%2')").arg(covered).arg(cmb->currentText()));
                shell->setOutsideNCTID(cmb->currentData().toInt());
                shell->setOutsideNCTCoveredArea(covered);
            }
            else 
            {
                _pyStr.append(QString("shell.setNCT(0,%1,'%2')").arg(covered).arg(cmb->currentText()));
                shell->setInsideNCTID(cmb->currentData().toInt());
                shell->setInsideNCTCoveredArea(covered);
            }
        }
    //Geometry板块数据提取
        double volume= -1, surface= -1, perimeter= -1;
        //如果启用 体积面积周长 的重载，判断输入是否合法
        if (_ui->checkBox_volume->isChecked()) {
            volume = _ui->lineEdit_volume->text().toDouble();
            if (fabs(volume) < 1e-16) {
                QMessageBox::warning(this, "", tr("The volume cannot be less than or equal to zero"), QMessageBox::Ok);
                return;
            }
        }
        else{
            _pyStr.append(QString("seaSubSys.setGeometryProp(1,0)"));
            cavityData->setVolume(volume);
        }
        if (_ui->checkBox_Surface->isChecked()) {
            surface = _ui->lineEdit_Surface->text().toDouble();
            if (surface < 0){
                QMessageBox::warning(this, "", tr("The surface cannot be less than zero"), QMessageBox::Ok);
                return;
            }
        }
        else {
            _pyStr.append(QString("seaSubSys.setGeometryProp(2,0)"));
            cavityData->setSurfaceArea(surface);
        }
        if (_ui->checkBox_Perimeter->isChecked()) {
            perimeter = _ui->lineEdit_Perimeter->text().toDouble();
            if (perimeter < 0) {
                QMessageBox::warning(this, "", tr("The perimeter cannot be less than zero"), QMessageBox::Ok);
                return;
            }
        }
        else {
            _pyStr.append(QString("seaSubSys.setGeometryProp(3,0)"));
            cavityData->setPerimeter(perimeter);
        }
        //更新 重载体积面积周长
        double data[3];
        data[0] = cavityData->getVolume();
        data[1] = cavityData->getSurfaceArea();
        data[2] = cavityData->getPerimeter();
        if (volume > 0 && (volume - data[0]<-1e-5 || volume - data[0] > 1e-5)) {
            _pyStr.append(QString("seaSubSys.setGeometryProp(1,1,%1)").arg(volume));
            cavityData->setVolume(volume);
        }
        if (surface >= 0 && (surface-data[1]<-1e-5|| surface - data[1] > 1e-5)) {
            _pyStr.append(QString("seaSubSys.setGeometryProp(2,1,%1)").arg(surface));
            cavityData->setSurfaceArea(surface);
        }
        if (perimeter >= 0 && (perimeter - data[2]<-1e-5 || perimeter - data[2] > 1e-5)) {
            _pyStr.append(QString("seaSubSys.setGeometryProp(3,1,%1)").arg(perimeter));
            cavityData->setPerimeter(perimeter);
        }

    //Pressure板块数据提取
        //是否启用压力
        bool pressure = _ui->checkBox_SMS->isChecked();
        cavityData->setInSEAMatrixSolution(pressure);
        //更新 模态密度
        int id = -1;
        if (_ui->checkBox_ModalDensity->isChecked()) {
            _pyStr.append(QString("seaSubSys.setSEAMatrixSolution_ModalDensity(%1,1,'%2')").arg(pressure).arg(_ui->comboBox_ModalDensity->currentText()));
            id=_ui->comboBox_ModalDensity->currentData().toInt();
            cavityData->setModalDensity(id);
        }
        else {
            _pyStr.append(QString("seaSubSys.setSEAMatrixSolution_ModalDensity(%1,0)").arg(pressure));
            cavityData->setModalDensity(id);
        }
    }

    QString GUISEASubSysCavityDialog::getNameFormWidget()
    {
        return _ui->lineEdit_Name->text();
    }

    void GUISEASubSysCavityDialog::on_pushButton_Cancel_clicked()
    {
        this->reject();
    }

    void GUISEASubSysCavityDialog::on_pushButton_OK_clicked()
    {
        if (!_oper||!_obj)return;
        //保存执行的脚本
        _pyStr.append("seaSubSys=SEA.SEACavity()");

        //获取操作器动作类型
        if (_isCreate)
        {
            Acoustics::FITKSEASubSysCavity* cavityData = dynamic_cast<Acoustics::FITKSEASubSysCavity*>(_obj);
            if (!cavityData) return;
            for (int i=0;i< cavityData->getShellCount();++i)
            {           
                _pyStr.append(QString("seaSubSys.addShell('%1')").arg(cavityData->getShellName(i)));
            }
            _pyStr.append("seaSubSys.createCavity()");
            if (!this->createObjData())
                return;
        }
        else
        {
            _pyStr.append(QString("seaSubSys=SEA.SEACavity.GetSEACavity('%1')").arg(_obj->getDataObjectName()));
            if (!this->editObjData())
                return;
        }
        this->saveScript(_pyStr);
        this->accept();
    }
    void GUISEASubSysCavityDialog::on_radioButton_Damping_toggled(bool checked)
    {
        if (checked == true)
            _ui->comboBox_Damping->setEnabled(true);
        else
            _ui->comboBox_Damping->setEnabled(false);
    }
    void GUISEASubSysCavityDialog::on_radioButton_Average_toggled(bool checked)
    {
        if (checked == true)
            _ui->comboBox_Average->setEnabled(true);
        else
            _ui->comboBox_Average->setEnabled(false);
    }
}

